<?php

namespace app\controller;

use app\common\lib\Common;


class IndexController extends CoreController
{
    public function test111()
	{
		$arr = config('param');
		return $this->endSuccess($arr);
	}

    public function autoRoute()
    {
        $controllerDirPath = app_path('controller');
        $this->getControllerAndMthod($controllerDirPath)->createRoute();
        return $this->endSuccess(['路由生成成功，请查看这个文件是否生成" '.runtime_path('route'.DIRECTORY_SEPARATOR.'web.php').' "']);

    }

    protected function createRoute()
    {
        $content = "<?php \n\n use Webman\Route; \n\n";
        $contentApi = "<?php \n\n use Illuminate\Support\Facades\Route; \n\n";
        $contentCron = "<?php \n\n use Illuminate\Support\Facades\Artisan; \n\n";
        $content2 = '';

        foreach($this->routeAdress as $namespace=>$routeData){

            $routeTextStart = '';
            $routeTextCenter = '';
            $routeTextEnd = '';

            $namespaces = array_slice(explode('\\',$namespace),2,-1);
            $fileName = array_slice(explode('\\',$namespace),-1)[0];

            if(!empty($namespaces[0]) && $namespaces[0]=='Cron'){
                $cronSpaceRoute = '';
                foreach($namespaces as $k=>$space){
                    $cronSpaceRoute .= strtolower($space).':';
                }
                $cronSpaceRoute .= strtolower(substr($fileName,0,strpos($fileName,'Controller'))).":";

                $contentCron .= "//$namespace \n";
                foreach($routeData as $method=>$value){
                    $cronRoute = $cronSpaceRoute.$method;

                    $contentCron .= "Artisan::command('{$cronRoute}',function (){\n";
                    $contentCron .= "       app()->crontabStartTime = microtime(true);\n";
                    $contentCron .= "       \$timedTask = config('crontab');\n";
                    $contentCron .= "       \$line = '\'php artisan {$cronRoute}\'';\n";
                    $contentCron .= "       \$lineKey = substr(md5(strtolower(\$line)),-10);\n";
                    $contentCron .= "       \$callback = '[app({$namespace}::class),\'{$method}\']';\n";
                    $contentCron .= "       \$callbackKey = substr(md5(strtolower(\$callback)),-10);\n";
                    $contentCron .= "       \$param = [];\n";
                    $contentCron .= "       \$value = [];\n\n";
                    $contentCron .= "        empty(\$value) && isset(\$timedTask[\$lineKey]) && \$value = \$timedTask[\$lineKey];\n";
                    $contentCron .= "        empty(\$value) && isset(\$timedTask[\$callbackKey]) && \$value = \$timedTask[\$callbackKey];\n";

                    $contentCron .= "        if(\$value){\n";
                    $contentCron .= "           \$param = !empty(\$value['param']) ? json_decode(\$value['param'], true) : [];\n";
                    $contentCron .= "           \$param['cronid'] = isset(\$value['cronid']) ? \$value['cronid'] : 0;\n";
                    $contentCron .= "       }\n";
                    $contentCron .= "       \$result = call_user_func([app({$namespace}::class),'{$method}'],\$param);\n";
                    $contentCron .= "       App\Model\Cron\CronTaskLog::getInstance()->insertTaskLog(\$value,\$result);\n";
                    $contentCron .= "});\n";
                }

            }else{
                foreach($namespaces as $k=>$space){
                    if($k==0){
                        $routeTextStart .= "Route::group('/{$space}',function(){ \n";
                        $routeTextEnd .= "});  \n";
                        continue;
                    }
                    $routeTextStart .= "    Route::group('/{$space}',function(){ \n";
                    $routeTextEnd = "    }); \n".$routeTextEnd;
                }

                foreach($routeData as $method=>$value){
                    $value['route'] = str_replace('\\','/',strtolower($value['route']));
                    $route = explode('/',$value['route']);
                    for($i=1;$i<=count($namespaces);$i++){
                        array_shift($route);
                    }
                    $value['route'] = implode('/',$route);

                    $routeTextCenter .= "         Route::{$value['method']}('/{$value['route']}',[\\{$namespace}::class,'{$method}']); \n";
                }

                if(!empty($namespaces[0]) && $namespaces[0]=='Api'){
                    $contentApi .= "//$namespace \n";
                    $contentApi .= $routeTextStart.$routeTextCenter.$routeTextEnd."\n";
                }else{
                    $content .= "//$namespace \n";
                    $content2 .= "//$namespace \n";
                    $content .= $routeTextStart.$routeTextCenter.$routeTextEnd."\n";
                    $content2 .= $routeTextStart.$routeTextCenter.$routeTextEnd."\n";
                }
            }



        }
        $routePath = runtime_path('routes');
        if(!is_dir($routePath)){
            Common::mkdirs($routePath);
        }

        $file = $routePath.DIRECTORY_SEPARATOR.'web.php';
        $fileApi = $routePath.DIRECTORY_SEPARATOR.'api.php';
        $fileCron = $routePath.DIRECTORY_SEPARATOR.'console.php';
        file_put_contents($file,$content);
        file_put_contents($fileApi,$contentApi);
        file_put_contents($fileCron,$contentCron);

        return $this;
    }

    protected function getControllerAndMthod($dirPath,$namespace='app\controller')
    {
        $noRoute = ['corecontroller.php','basecontroller.php'];
        foreach (scandir($dirPath) as $dir){
            $filePath = $dirPath.DIRECTORY_SEPARATOR.$dir;
            if($dir=='.' || $dir=='..'){
                continue;
            }
            if(is_dir($filePath)){
                $this->getControllerAndMthod($filePath,$namespace.'\\'.$dir);

            }elseif (is_file($filePath)){

                if(in_array(strtolower($dir), $noRoute)){
                    continue;
                }
                if(strpos(strtolower($dir),'controller')===false){
                    continue;
                }

                $name = explode('.',$dir)[0];
                $namespaces = $namespace.'\\'.$name;

                $oReflectionClass = new \ReflectionClass($namespaces);
                $methods = $oReflectionClass->getMethods();
                foreach($methods as $method){
                    if($method->class != $namespaces){
                        continue;
                    }
                    if($method->name == '__construct'){
                        continue;
                    }

                    $methodObj = $oReflectionClass->getMethod($method->name);
                    if($methodObj->isPublic()){
                        $address = str_replace([strtolower('app\\controller\\'),'controller'],[''],strtolower($namespaces));

                        $this->routeAdress[$namespaces][$method->name]['route'] = $address.'\\'.$method->name;
                        //$this->routeAdress[$namespaces][$method->name]['namespace'] = explode('\\',$address);
                        if(strpos(strtolower($namespaces),'index\\notifycontroller')!==false){
                            $this->routeAdress[$namespaces][$method->name]['method'] = 'any';
                        }elseif(strpos(strtolower($namespaces),'test\\viewlogcontroller')!==false){
                            $this->routeAdress[$namespaces][$method->name]['method'] = 'any';
                        }elseif(strpos($method->name,'index')===0 || strpos($method->name,'get')===0){
                            $this->routeAdress[$namespaces][$method->name]['method'] = 'get';
                        }else{
                            $this->routeAdress[$namespaces][$method->name]['method'] = 'post';
                        }
                    }
                }
            }
        }

        return $this;
    }
}
